Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
| Total | |
100.00% |
1 / 1 |
|
100.00% |
13 / 13 |
CRAP | |
100.00% |
73 / 73 |
| AddVersionSubscriber | |
100.00% |
1 / 1 |
|
100.00% |
13 / 13 |
29 | |
100.00% |
73 / 73 |
| __construct | |
100.00% |
1 / 1 |
1 | |
100.00% |
2 / 2 |
|||
| getSubscribedEvents | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
| onFlush | |
100.00% |
1 / 1 |
6 | |
100.00% |
13 / 13 |
|||
| postFlush | |
100.00% |
1 / 1 |
1 | |
100.00% |
2 / 2 |
|||
| processVersionableEntities | |
100.00% |
1 / 1 |
3 | |
100.00% |
10 / 10 |
|||
| createVersion | |
100.00% |
1 / 1 |
3 | |
100.00% |
9 / 9 |
|||
| checkScheduledUpdate | |
100.00% |
1 / 1 |
2 | |
100.00% |
5 / 5 |
|||
| checkScheduledCollection | |
100.00% |
1 / 1 |
2 | |
100.00% |
5 / 5 |
|||
| checkScheduledDeletion | |
100.00% |
1 / 1 |
2 | |
100.00% |
5 / 5 |
|||
| addPendingVersioning | |
100.00% |
1 / 1 |
3 | |
100.00% |
4 / 4 |
|||
| computeChangeSet | |
100.00% |
1 / 1 |
2 | |
100.00% |
6 / 6 |
|||
| getObjectHash | |
100.00% |
1 / 1 |
1 | |
100.00% |
4 / 4 |
|||
| detachVersions | |
100.00% |
1 / 1 |
2 | |
100.00% |
7 / 7 |
|||
| <?php | |
| namespace Akeneo\Tool\Bundle\VersioningBundle\EventSubscriber; | |
| use Akeneo\Tool\Bundle\VersioningBundle\UpdateGuesser\UpdateGuesserInterface; | |
| use Akeneo\Tool\Component\Versioning\Model\Version; | |
| use Doctrine\Common\EventSubscriber; | |
| use Doctrine\Common\Util\ClassUtils; | |
| use Doctrine\ORM\EntityManager; | |
| use Doctrine\ORM\Event\OnFlushEventArgs; | |
| use Doctrine\ORM\Event\PostFlushEventArgs; | |
| use Symfony\Component\DependencyInjection\ContainerInterface; | |
| /** | |
| * Aims to audit data updates on versionable entities | |
| * | |
| * @author Nicolas Dupont <nicolas@akeneo.com> | |
| * @copyright 2013 Akeneo SAS (http://www.akeneo.com) | |
| * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) | |
| */ | |
| class AddVersionSubscriber implements EventSubscriber | |
| { | |
| /** @var object[] */ | |
| protected $versionableEntities = []; | |
| /** @var string[] */ | |
| protected $versionedEntities = []; | |
| /** @var string[] */ | |
| protected $versions = []; | |
| /** @var ContainerInterface */ | |
| protected $container; | |
| /** | |
| * Constructor. We have to inject the container here as Doctrine event subscribers throws circular | |
| * reference dependency exceptions if we try to inject services that requiring doctrine. | |
| * For instance the dependency occurs with the version manager. | |
| * | |
| * @param ContainerInterface $container | |
| */ | |
| public function __construct(ContainerInterface $container) | |
| { | |
| $this->container = $container; | |
| } | |
| /** | |
| * Specifies the list of events to listen | |
| * | |
| * @return string[] | |
| */ | |
| public function getSubscribedEvents() | |
| { | |
| return ['onFlush', 'postFlush']; | |
| } | |
| /** | |
| * @param OnFlushEventArgs $args | |
| */ | |
| public function onFlush(OnFlushEventArgs $args) | |
| { | |
| $em = $args->getEntityManager(); | |
| $uow = $em->getUnitOfWork(); | |
| foreach ($uow->getScheduledEntityInsertions() as $entity) { | |
| $this->checkScheduledUpdate($em, $entity); | |
| } | |
| foreach ($uow->getScheduledEntityUpdates() as $entity) { | |
| $this->checkScheduledUpdate($em, $entity); | |
| } | |
| foreach ($uow->getScheduledEntityDeletions() as $entity) { | |
| $this->checkScheduledDeletion($em, $entity); | |
| } | |
| foreach ($uow->getScheduledCollectionDeletions() as $entity) { | |
| $this->checkScheduledCollection($em, $entity); | |
| } | |
| foreach ($uow->getScheduledCollectionUpdates() as $entity) { | |
| $this->checkScheduledCollection($em, $entity); | |
| } | |
| } | |
| /** | |
| * @param PostFlushEventArgs $args | |
| */ | |
| public function postFlush(PostFlushEventArgs $args) | |
| { | |
| $this->processVersionableEntities(); | |
| } | |
| /** | |
| * Process the entities to be versioned | |
| */ | |
| protected function processVersionableEntities() | |
| { | |
| foreach ($this->versionableEntities as $versionable) { | |
| $oid = $this->getObjectHash($versionable); | |
| $this->createVersion($versionable); | |
| $this->versionedEntities[] = $oid; | |
| } | |
| $versionedCount = count($this->versionableEntities); | |
| $this->versionableEntities = []; | |
| if ($versionedCount) { | |
| $this->container->get('pim_versioning.manager.version')->getObjectManager()->flush(); | |
| $this->detachVersions(); | |
| } | |
| } | |
| /** | |
| * @param object $versionable | |
| */ | |
| protected function createVersion($versionable) | |
| { | |
| $changeset = []; | |
| if (!$this->container->get('pim_versioning.manager.version')->isRealTimeVersioning()) { | |
| $changeset = $this->container->get('pim_versioning.serializer') | |
| ->normalize($versionable, 'flat', ['versioning' => true]); | |
| } | |
| $versions = $this->container->get('pim_versioning.manager.version')->buildVersion($versionable, $changeset); | |
| foreach ($versions as $version) { | |
| $this->versions[] = $version; | |
| $this->computeChangeSet($version); | |
| } | |
| } | |
| /** | |
| * Check if an entity must be versioned due to entity changes | |
| * | |
| * @param EntityManager $em | |
| * @param object $entity | |
| */ | |
| protected function checkScheduledUpdate($em, $entity) | |
| { | |
| $pendings = $this->container->get('pim_versioning.update_guesser.chained') | |
| ->guessUpdates($em, $entity, UpdateGuesserInterface::ACTION_UPDATE_ENTITY); | |
| foreach ($pendings as $pending) { | |
| $this->addPendingVersioning($pending); | |
| } | |
| } | |
| /** | |
| * Check if an entity must be versioned due to collection changes | |
| * | |
| * @param EntityManager $em | |
| * @param object $entity | |
| */ | |
| protected function checkScheduledCollection($em, $entity) | |
| { | |
| $pendings = $this->container->get('pim_versioning.update_guesser.chained') | |
| ->guessUpdates($em, $entity, UpdateGuesserInterface::ACTION_UPDATE_COLLECTION); | |
| foreach ($pendings as $pending) { | |
| $this->addPendingVersioning($pending); | |
| } | |
| } | |
| /** | |
| * Check if a related entity must be versioned due to entity deletion | |
| * | |
| * @param EntityManager $em | |
| * @param object $entity | |
| */ | |
| protected function checkScheduledDeletion($em, $entity) | |
| { | |
| $pendings = $this->container->get('pim_versioning.update_guesser.chained') | |
| ->guessUpdates($em, $entity, UpdateGuesserInterface::ACTION_DELETE); | |
| foreach ($pendings as $pending) { | |
| $this->addPendingVersioning($pending); | |
| } | |
| } | |
| /** | |
| * Mark entity as to be versioned | |
| * | |
| * @param object $versionable | |
| */ | |
| protected function addPendingVersioning($versionable) | |
| { | |
| $oid = $this->getObjectHash($versionable); | |
| if (!isset($this->versionableEntities[$oid]) && !in_array($oid, $this->versionedEntities)) { | |
| $this->versionableEntities[$oid] = $versionable; | |
| } | |
| } | |
| /** | |
| * Compute version change set | |
| * | |
| * @param Version $version | |
| */ | |
| protected function computeChangeSet(Version $version) | |
| { | |
| $om = $this->container->get('pim_versioning.manager.version')->getObjectManager(); | |
| if ($version->getChangeset()) { | |
| $om->persist($version); | |
| $om->getUnitOfWork()->computeChangeSet($om->getClassMetadata(ClassUtils::getClass($version)), $version); | |
| } else { | |
| $om->remove($version); | |
| } | |
| } | |
| /** | |
| * Get an object hash, provides different hashes depending on version manager context to allows to log different | |
| * versions of a same object during a request | |
| * | |
| * @param object $object | |
| * | |
| * @return string | |
| */ | |
| protected function getObjectHash($object) | |
| { | |
| return sprintf( | |
| '%s#%s', | |
| spl_object_hash($object), | |
| sha1($this->container->get('pim_versioning.context.version')->getContextInfo()) | |
| ); | |
| } | |
| /** | |
| * Clear versions know to this subscribler from the object manager | |
| */ | |
| protected function detachVersions() | |
| { | |
| $om = $this->container->get('pim_versioning.manager.version')->getObjectManager(); | |
| foreach ($this->versions as $version) { | |
| $om->detach($version); | |
| } | |
| $this->versions = []; | |
| $this->versionableEntities = []; | |
| $this->versionedEntities = []; | |
| } | |
| } |